package fr.sedoo.commons.client.widget.table;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.AbstractDataProvider;
import com.google.gwt.view.client.ListDataProvider;

import fr.sedoo.commons.client.message.CommonMessages;
import fr.sedoo.commons.client.widget.ConfirmCallBack;
import fr.sedoo.commons.client.widget.DialogBoxTools;
import fr.sedoo.commons.client.widget.style.CellTableResources;
import fr.sedoo.commons.shared.domain.HasIdentifier;

public abstract class AbstractTable extends Composite implements ClickHandler {

	protected FormattedCellTable<HasIdentifier> itemTable;
	protected VerticalPanel tablePanel;
	private HorizontalPanel toolBarPanel;
	protected HorizontalPanel headerPanel;
	private Image addImage;
	protected Label addItemLabel;
	private final Image deleteImage = new Image(TableBundle.INSTANCE.delete());
	protected final Image editImage = new Image(TableBundle.INSTANCE.edit());

	protected Column<HasIdentifier, String> deleteColumn;
	protected Column<HasIdentifier, String> editColumn;

	public abstract void presenterDelete(HasIdentifier hasId);

	public abstract void presenterEdit(HasIdentifier hasId);

	protected HorizontalPanel emptyListPanel;

	private boolean addButtonEnabled = false;

	private boolean askDeletionConfirmation = true;

	public AbstractTable() {
		super();

		if (tablePanel == null) {
			tablePanel = new VerticalPanel();
		} else {
			tablePanel.clear();
		}

		emptyListPanel = new HorizontalPanel();
		emptyListPanel.add(new Label(CommonMessages.INSTANCE.emptyList()));

		checkEmptyPanelVisibility();

		tablePanel.add(emptyListPanel);

		itemTable = new FormattedCellTable<HasIdentifier>(Integer.MAX_VALUE, CellTableResources.INSTANCE);
		itemTable.setWidth("100%", false);

		setToolBarPanel(new HorizontalPanel());
		getToolBarPanel().setSpacing(5);
		headerPanel = new HorizontalPanel();
		headerPanel.setSpacing(5);
		setHeaderPanelVisible(false);
		// addItemPanel.setWidth("100%");
		addImage = new Image(TableBundle.INSTANCE.add());
		addImage.setStyleName("clickable");
		getToolBarPanel().add(addImage);
		addItemLabel = new Label(getAddItemText());
		addItemLabel.setStyleName("clickable");
		getToolBarPanel().add(addItemLabel);
		tablePanel.add(headerPanel);
		tablePanel.add(itemTable);
		tablePanel.add(getToolBarPanel());
		tablePanel.setWidth("100%");
		addImage.addClickHandler(this);
		addItemLabel.addClickHandler(this);

		Cell<HasIdentifier> deleteActionCell = new ImagedActionCell<HasIdentifier>(deleteAction, deleteImage, CommonMessages.INSTANCE.delete());
		deleteColumn = new Column(deleteActionCell) {

			@Override
			public HasIdentifier getValue(Object object) {
				return (HasIdentifier) object;
			}
		};

		Cell<HasIdentifier> editActionCell = new ImagedActionCell<HasIdentifier>(editAction, editImage, CommonMessages.INSTANCE.edit());
		editColumn = new Column(editActionCell) {

			@Override
			public HasIdentifier getValue(Object object) {
				return (HasIdentifier) object;
			}
		};

		initColumns();
		initWidget(tablePanel);

	}

	protected AbstractDataProvider<HasIdentifier> getDataProvider() {
		return new ListDataProvider<HasIdentifier>();
	}

	protected void checkEmptyPanelVisibility() {
		if (isEmpty()) {
			emptyListPanel.setVisible(true);
			if (itemTable != null) {
				itemTable.setVisible(false);
			}
		} else {
			emptyListPanel.setVisible(false);
			if (itemTable != null) {
				itemTable.setVisible(true);
			}
		}
	}

	protected void initColumns() {
		itemTable.addColumn(editColumn);
		itemTable.addColumn(deleteColumn);
		itemTable.setColumnWidth(editColumn, 30.0, Unit.PX);
		itemTable.setColumnWidth(deleteColumn, 30.0, Unit.PX);
	}

	protected void addEditColumn() {
		itemTable.addColumn(editColumn);
		itemTable.setColumnWidth(editColumn, 30.0, Unit.PX);
	}

	protected void addDeleteColumn() {
		itemTable.addColumn(deleteColumn);
		itemTable.setColumnWidth(deleteColumn, 30.0, Unit.PX);
	}

	public abstract void addItem();

	public abstract boolean isEmpty();

	@Override
	public void onClick(ClickEvent event) {
		if ((event.getSource() == addImage) || (event.getSource() == addItemLabel)) {
			if (addButtonEnabled == true) {
				addItem();
			} else {
				DialogBoxTools.modalAlert("Not activated", "Not activated in this mode");
			}
		}
	}

	public abstract String getAddItemText();

	public String getDeleteItemConfirmationText() {
		return CommonMessages.INSTANCE.deletionConfirmMessage();
	}

	public void setAddButtonEnabled(boolean activated) {
		this.addButtonEnabled = activated;
	}

	public boolean isAskDeletionConfirmation() {
		return askDeletionConfirmation;
	}

	public void setAskDeletionConfirmation(boolean askDeletionConfirmation) {
		this.askDeletionConfirmation = askDeletionConfirmation;
	}

	public void setToolBarPanelVisible(boolean value) {
		getToolBarPanel().setVisible(value);
	}

	public void setHeaderPanelVisible(boolean value) {
		headerPanel.setVisible(value);
	}

	protected ImagedActionCell.Delegate<HasIdentifier> deleteAction = new ImagedActionCell.Delegate<HasIdentifier>() {

		@Override
		public void execute(final HasIdentifier hasId) {

			if (isAskDeletionConfirmation() == false) {
				presenterDelete(hasId);
			} else {
				ConfirmCallBack callBack = new ConfirmCallBack() {

					@Override
					public void confirm(boolean choice) {
						if (choice == true) {
							presenterDelete(hasId);
						}

					}
				};

				DialogBoxTools.modalConfirm(CommonMessages.INSTANCE.confirm(), getDeleteItemConfirmationText(), callBack).center();
			}
		}

	};

	protected ImagedActionCell.Delegate<HasIdentifier> editAction = new ImagedActionCell.Delegate<HasIdentifier>() {

		@Override
		public void execute(HasIdentifier hasCode) {

			presenterEdit(hasCode);

		}

	};

	public void hideToolBar() {
		getToolBarPanel().setVisible(false);
	}

	public void showToolBar() {
		getToolBarPanel().setVisible(true);
	}

	public void hideHeader() {
		itemTable.hideHeader();
	}

	protected void clearColumns() {
		int columnCount = itemTable.getColumnCount();
		for (int i = columnCount - 1; i >= 0; i--) {
			itemTable.removeColumn(i);
		}
	}

	public HorizontalPanel getToolBarPanel() {
		return toolBarPanel;
	}

	public void setToolBarPanel(HorizontalPanel toolBarPanel) {
		this.toolBarPanel = toolBarPanel;
	}

}
